<?php
/**
 * Model for a project build.
 *
 * @category PhpCilux
 * @package  PhpCilux
 */

/**
 * Model for a project build.
 *
 * @package PhpCilux
 */
class Model_Build
{

    /**
     * The project key.
     *
     * @var string
     */
    protected $_projectKey;

    /**
     * The build key.
     *
     * @var string
     */
    protected $_buildKey;

    /**
     * Constructor.
     *
     * @param array $options Several options (key -> value).
     */
    public function __construct(array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Magic setter.
     *
     * @param mixed $name  The property name.
     * @param mixed $value The property value.
     *
     * @return void
     * @throws Exception Invalid property.
     */
    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (!method_exists($this, $method)) {
            throw new Exception('Invalid property');
        }

        $this->$method($value);
    }

    /**
     * Magic getter.
     *
     * @param mixed $name The property name.
     *
     * @return mixed The value.
     * @throws Exception Invalid property.
     */
    public function __get($name)
    {
        $method = 'get' . $name;
        if (!method_exists($this, $method)) {
            throw new Exception('Invalid property');
        }

        return $this->$method();
    }

    /**
     * Set several options.
     *
     * @param array $options Several options (key -> value).
     *
     * @return Model_Project
     */
    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . (str_replace(' ', '', ucwords(str_replace('_', ' ', $key))));
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }

        return $this;
    }

    /**
     * Set the project key.
     *
     * @param string $text The project key.
     *
     * @return Model_Build
     */
    public function setProjectKey($text)
    {
        $this->_projectKey = (string) $text;
        return $this;
    }

    /**
     * Get the project key.
     *
     * @return string
     */
    public function getProjectKey()
    {
        return $this->_projectKey;
    }

    /**
     * Set the build key.
     *
     * @param string $text The build key.
     *
     * @return Model_Build
     */
    public function setBuildKey($text)
    {
        $this->_buildKey = (string) $text;
        return $this;
    }

    /**
     * Get the build key.
     *
     * @return string
     */
    public function getBuildKey()
    {
        return $this->_buildKey;
    }

    /**
     * Get the build status.
     *
     * @return string
     */
    public function getStatus()
    {
        if ($this->hasPhpUnit() && $this->statusPhpUnit() == 'failed') {
            return 'failed';
        }

        if ($this->hasPhpCs() && $this->statusPhpCs() == 'failed') {
            return 'failed';
        }

        return 'success';
    }

    /**
     * Get the build name.
     *
     * @return string 
     */
    public function getName()
    {
        return $this->getBuildKey();
    }

    /**
     * Has the build a PHP Unit log.
     *
     * @return boolean
     */
    public function hasPhpUnit()
    {
        return Model_BuildMapper::getInstance()->exitsLog($this->_projectKey, $this->_buildKey, 'phpunit');
    }

    /**
     * Get the log content for the PHP Unit log.
     *
     * @return string
     */
    public function getPhpUnit()
    {
        return Model_BuildMapper::getInstance()->getLog($this->_projectKey, $this->_buildKey, 'phpunit');
    }

    /**
     * Get the status of the PHP Unit log.
     *
     * @return string
     */
    public function statusPhpUnit()
    {
        $log        = $this->getPhpUnit();
        $lines      = explode("\n", $log);
        $totalLines = count($lines);

        $line = $lines[($totalLines - 2)];
        $pos  = stripos($line, '[2K');

        if ($pos !== false) {
            $line = substr($line, ($pos + 3));
        }

        if ('OK' == substr($line, 0, 2)) {
            return 'success';
        }

        return 'failed';
    }

    /**
     * Has the build a PHP Codesniffer log.
     *
     * @return boolean
     */
    public function hasPhpCs()
    {
        return Model_BuildMapper::getInstance()->exitsLog($this->_projectKey, $this->_buildKey, 'phpcs');
    }

    /**
     * Get the log content for the PHP Codesniffer log.
     *
     * @return string
     */
    public function getPhpCs()
    {
        return Model_BuildMapper::getInstance()->getLog($this->_projectKey, $this->_buildKey, 'phpcs');
    }

    /**
     * Get the status of the PHP Codesniffer log.
     *
     * @return string
     */
    public function statusPhpCs()
    {
        $log   = $this->getPhpCs();
        $lines = explode("\n", $log);

        while (list($key, $line) = each($lines)) {
            $line = rtrim($line);

            if (false !== stripos($line, '| ERROR |')) {
                return 'failed';
            }
        }

        return 'success';
    }

    /**
     * Get the commit comment.
     *
     * @return string
     */
    public function getCommitComment()
    {
        return Model_BuildMapper::getInstance()->getCommitComment($this->_projectKey, $this->_buildKey);
    }

    /**
     * Get the commit author.
     *
     * @return string
     */
    public function getCommitAuthor()
    {
        return Model_BuildMapper::getInstance()->getCommitAuthor($this->_projectKey, $this->_buildKey);
    }

    /**
     * Get the commit time.
     *
     * @return string
     */
    public function getCommitTime()
    {
        return Model_BuildMapper::getInstance()->getCommitTime($this->_projectKey, $this->_buildKey);
    }

}